package cn.ug.pay.service.impl;

import cn.ug.bean.base.SerializeObject;
import cn.ug.bean.type.ResultType;
import cn.ug.config.CacheUtilsService;
import cn.ug.config.FundRateConfig;
import cn.ug.config.RedisGlobalLock;
import cn.ug.core.ensure.Ensure;
import cn.ug.enums.OrderNOPrefixEnum;
import cn.ug.enums.RateKeyEnum;
import cn.ug.enums.WxTemplateEnum;
import cn.ug.feign.PriceService;
import cn.ug.feign.RateSettingsService;
import cn.ug.msg.bean.status.CommonConstants;
import cn.ug.msg.mq.Msg;
import cn.ug.msg.mq.WxMessageParamBean;
import cn.ug.msg.mq.WxNotifyData;
import cn.ug.pay.bean.BillBean;
import cn.ug.pay.bean.MemberGoldBean;
import cn.ug.pay.bean.enumeration.TbillStatusRemark;
import cn.ug.pay.bean.enumeration.TbillTypeEnum;
import cn.ug.pay.bean.status.TbillStatusEnum;
import cn.ug.pay.bean.type.BillGoldTradeType;
import cn.ug.pay.bean.type.BillType;
import cn.ug.pay.bean.type.TradeType;
import cn.ug.pay.mapper.*;
import cn.ug.pay.mapper.entity.*;
import cn.ug.pay.service.PayTbillSoldService;
import cn.ug.util.BigDecimalUtil;
import cn.ug.util.DateUtils;
import cn.ug.util.SerialNumberWorker;
import cn.ug.util.UF;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;

import static cn.ug.config.QueueName.QUEUE_MSG_SEND;
import static cn.ug.config.QueueName.QUEUE_MSG_WX_SEND;

@Service
public class PayTbillSoldServiceImpl implements PayTbillSoldService {
    private Log log = LogFactory.getLog(PayTbillSoldServiceImpl.class);
    @Autowired
    private PayTbillSoldMapper payTbillSoldMapper;
    @Autowired
    private RedisGlobalLock redisGlobalLock;
    @Autowired
    private PayTbillMapper payTbillMapper;
    @Autowired
    private PayTbillStatisticsMapper payTbillStatisticsMapper;
    @Autowired
    private MemberAccountMapper memberAccountMapper;
    @Autowired
    private BillMapper billMapper;
    @Autowired
    private PriceService priceService;
    @Autowired
    private RateSettingsService rateSettingsService;
    @Autowired
    private FundRateConfig fundRateConfig;
    @Autowired
    private CacheUtilsService cacheUtilsService;
    @Autowired
    private PayTbillStatusMapper payTbillStatusMapper;
    @Autowired
    private AmqpTemplate amqpTemplate;

    @Override
    public BigDecimal getFee(String memberId, BigDecimal totalGram, BigDecimal goldPrice) {
        if (StringUtils.isBlank(memberId) || BigDecimalUtil.isZeroOrNull(totalGram) || BigDecimalUtil.isZeroOrNull(goldPrice)) {
            return null;
        }
        BigDecimal totalAmount = BigDecimalUtil.multiply(goldPrice, totalGram);
        BigDecimal fee = BigDecimal.ZERO;
        SerializeObject rateBean = rateSettingsService.get(RateKeyEnum.SELL_GOLD.getKey());
        if (rateBean != null && rateBean.getData() != null) {
            JSONObject json = JSON.parseObject(JSONObject.toJSONString(rateBean.getData()));
            int dayNum = billMapper.getTransactionNumForThisDay(memberId, TradeType.TBILL_SOLD.getValue());
            int monthNum = billMapper.getTransactionNumForThisMonth(memberId, TradeType.TBILL_SOLD.getValue());
            fee = fundRateConfig.getSellGoldFee(json, totalAmount, totalGram, dayNum, monthNum);
        }
        return fee;
    }

    @Override
    public PayTbillSold selectByOrderNO(String orderNO) {
        if (StringUtils.isNotBlank(orderNO)) {
            return payTbillSoldMapper.selectByOrderNO(orderNO);
        }
        return null;
    }

    @Override
    public PayTbillSold selectByTbillNO(String tbillNO) {
        if (StringUtils.isNotBlank(tbillNO)) {
            return payTbillSoldMapper.selectByTbillNO(tbillNO);
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String sale(String orderNO, String goldPriceKey) {
        String key = "PayTbillSoldServiceImpl:sale:" + orderNO;
        if (!redisGlobalLock.lock(key)) {
            return null;
        }
        try {
            PayTbill payTbill = payTbillMapper.selectByOrderNO(orderNO);
            if (payTbill == null || payTbill.getStatus() != TbillStatusEnum.PAY_SUCCESS.getStatus()) {
                return null;
            }
            PayTbillStatistics payTbillStatistics = payTbillStatisticsMapper.selectByMemberId(payTbill.getMemberId());
            if (payTbillStatistics == null) {
                return null;
            }
            BigDecimal weight = new BigDecimal(payTbill.getTotalGram());
            String date = UF.getFormatDateNow();
            SerializeObject result = rateSettingsService.get(RateKeyEnum.BUY_SELL_GRAM.getKey());
            if (result.getData() != null) {
                Map<String, Object> map = (Map<String, Object>) result.getData();
                String maxGramPerday = String.valueOf(map.get("sellMaxGramPerDay"));
                if (!"0".equals(maxGramPerday)) {
                    BigDecimal sellTotalGram = new BigDecimal(payTbillSoldMapper.sumSomedaySoldGram(payTbill.getMemberId(), date));
                    sellTotalGram = BigDecimalUtil.subtract(new BigDecimal(maxGramPerday), sellTotalGram);
                    if (weight.compareTo(sellTotalGram) > 0) {
                        Ensure.that(true).isTrue("17000710");
                    }
                }
            }
            String saleNO = OrderNOPrefixEnum.TS.name() + SerialNumberWorker.getInstance().nextId();
            // 1. 添加出售记录；
            PayTbillSold payTbillSold = new PayTbillSold();
            payTbillSold.setTbillNO(orderNO);
            payTbillSold.setOrderNO(saleNO);
            String hashKey = goldPriceKey + orderNO;
            Object cacheGoldPrice = cacheUtilsService.getCache(hashKey);
            if (null == cacheGoldPrice) {
                Ensure.that(true).isTrue("00000005");
            }
            BigDecimal goldPrice = new BigDecimal(cacheGoldPrice.toString());
            payTbillSold.setGoldPrice(goldPrice);
            payTbillSold.setTotalAmount(BigDecimalUtil.to2Point(new BigDecimal(payTbill.getTotalGram()).multiply(goldPrice)));
            BigDecimal fee = getFee(payTbill.getMemberId(), new BigDecimal(payTbill.getTotalGram()), goldPrice);
            payTbillSold.setFee(fee);
            BigDecimal couponAmount = BigDecimal.ZERO;
            if (StringUtils.isNotBlank(payTbill.getCouponId())) {
                if (payTbill.getLeasebackTimes() == 0) {
                    LocalDateTime startTime = UF.getDateTime(payTbill.getAddTime());
                    LocalDateTime endTime = LocalDateTime.now();
                    Duration duration = Duration.between(startTime, endTime);
                    long days = duration.toDays();
                    //long hours = duration.toHours();
                    if (days < 30) {
                        couponAmount = payTbill.getCouponGram().multiply(payTbill.getGoldPrice());
                    }
                }
            }
            payTbillSold.setCouponAmount(couponAmount);
            payTbillSold.setActualAmount(BigDecimalUtil.to2Point(new BigDecimal(payTbill.getTotalGram()).multiply(goldPrice).subtract(fee).subtract(payTbillSold.getCouponAmount())));
            payTbillSold.setAddTime(UF.getFormatDateTime(UF.getDateTime()));
            payTbillSold.setSuccessTime(UF.getFormatDateTime(UF.getDateTime()));
            int rows = payTbillSoldMapper.insert(payTbillSold);
            Ensure.that(rows).isLt(1, "00000005");
            // 2. 更改提单表信息；
            Map<String, Object> param = new HashMap<String, Object>();
            param.put("orderNO", orderNO);
            param.put("status", TbillStatusEnum.SOLD.getStatus());
            param.put("modifyTime", UF.getFormatDateTime(UF.getDateTime()));
            param.put("readed", 0);
            rows = payTbillMapper.update(param);
            Ensure.that(rows).isLt(1, "00000005");
            // 3. 更改提单统计表信息；
            Map<String, Object> staParam = new HashMap<String, Object>();
            staParam.put("memberId", payTbill.getMemberId());
            staParam.put("pendingBills", payTbillStatistics.getPendingBills() - 1);
            staParam.put("pendingGram", payTbillStatistics.getPendingGram() - payTbill.getTotalGram());
            staParam.put("soldBills", payTbillStatistics.getSoldBills() + 1);
            staParam.put("soldGram", payTbillStatistics.getSoldGram() + payTbill.getTotalGram());
            staParam.put("soldAmount", payTbillStatistics.getSoldAmount().add(payTbillSold.getActualAmount()));
            rows = payTbillStatisticsMapper.update(staParam);
            Ensure.that(rows).isLt(1, "00000005");
            // 4. 奖励发放
            MemberAccount memberAccount = memberAccountMapper.findByMemberId(payTbill.getMemberId());
            Ensure.that(memberAccount == null).isTrue("17000421");
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("id", memberAccount.getId());
            map.put("fundAmount", memberAccount.getFundAmount().add(payTbillSold.getActualAmount()));
            map.put("usableAmount", memberAccount.getUsableAmount().add(payTbillSold.getActualAmount()));
            rows = memberAccountMapper.updateByPrimaryKeySelective(map);
            Ensure.that(rows).isLt(1, "00000005");
            // 5. 新增收支记录
            Bill billBean = new Bill();
            billBean.setOrderId(SerialNumberWorker.getInstance().nextId());
            billBean.setMemberId(payTbill.getMemberId());
            billBean.setAmount(payTbillSold.getTotalAmount());
            billBean.setFee(payTbillSold.getFee());
            billBean.setActualAmount(payTbillSold.getActualAmount());
            billBean.setType(BillType.INCOME.getValue());
            billBean.setId(UF.getRandomUUID());
            billBean.setTradeType(TradeType.TBILL_SOLD.getValue());
            billBean.setOrderId(SerialNumberWorker.getInstance().nextId());
            rows = billMapper.insert(billBean);
            Ensure.that(rows).isLt(1, "00000005");
            // 6. 提单出售手续费收支记录
            if (fee.doubleValue() > 0) {
                billBean = new Bill();
                billBean.setOrderId(SerialNumberWorker.getInstance().nextId());
                billBean.setMemberId(payTbill.getMemberId());
                billBean.setAmount(fee);
                billBean.setFee(BigDecimal.ZERO);
                billBean.setActualAmount(fee.subtract(BigDecimal.ZERO));
                billBean.setType(BillType.OUTLAY.getValue());
                billBean.setId(UF.getRandomUUID());
                billBean.setTradeType(TradeType.TBILL_SOLD_FEE.getValue());
                billBean.setOrderId(SerialNumberWorker.getInstance().nextId());
                rows = billMapper.insert(billBean);
                Ensure.that(rows).isLt(1, "00000005");
            }
            PayTbillStatus payTbillStatus = new PayTbillStatus();
            payTbillStatus.setTbillNO(orderNO);
            payTbillStatus.setOrderNO(SerialNumberWorker.getInstance().nextId());
            payTbillStatus.setAddTime(UF.getFormatDateTime(UF.getDateTime()));
            payTbillStatus.setType(TbillTypeEnum.SOLD.getValue());
            payTbillStatus.setStatus(TbillStatusEnum.SOLD.getStatus());
            payTbillStatus.setRemark(TbillStatusRemark.SOLD.getValue());
            payTbillStatus.setModifyTime(UF.getFormatDateTime(UF.getDateTime()));
            payTbillStatusMapper.insert(payTbillStatus);
            // 7. 消息通知
            Msg msg = new Msg();
            msg.setMemberId(payTbill.getMemberId());
            msg.setType(CommonConstants.MsgType.SELL_GOLD.getIndex());
            Map<String, String> paramMap = new HashMap<>();
            paramMap.put("reduceGram", String.valueOf(payTbill.getTotalGram()));
            paramMap.put("gram", String.valueOf(payTbillStatistics.getPendingGram() - payTbill.getTotalGram()));
            msg.setParamMap(paramMap);
            amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);

            WxMessageParamBean wxMessageParamBean = new WxMessageParamBean();
            wxMessageParamBean.setMemberId(payTbill.getMemberId());
            wxMessageParamBean.setType(WxTemplateEnum.SALE_GOLD_SUCCEED.getType());
            WxTemplateEnum wxTemplateEnum = WxTemplateEnum.getWxTemplateByCode(WxTemplateEnum.SALE_GOLD_SUCCEED.getType());
            WxNotifyData wxNotifyData = new WxNotifyData();

            Map<String, WxNotifyData.TemplateDataAttr> wxParamMap = new HashMap();
            WxNotifyData.TemplateDataAttr first = new WxNotifyData.TemplateDataAttr();
            first.setDataValue(wxTemplateEnum.getFirstData().replace("{weight}", String.valueOf(payTbill.getTotalGram())).
                    replace("{balance}", String.valueOf(payTbillStatistics.getPendingGram() - payTbill.getTotalGram())).
                    replace("{money}", String.valueOf(payTbillSold.getActualAmount())));
            wxParamMap.put("first", first);

            WxNotifyData.TemplateDataAttr keyword1 = new WxNotifyData.TemplateDataAttr();
            keyword1.setDataValue(String.valueOf(payTbillSold.getActualAmount()));
            wxParamMap.put("keyword1", keyword1);

            WxNotifyData.TemplateDataAttr keyword2 = new WxNotifyData.TemplateDataAttr();
            keyword2.setDataValue(String.valueOf(payTbill.getTotalGram()));
            wxParamMap.put("keyword2", keyword2);

            WxNotifyData.TemplateDataAttr keyword3 = new WxNotifyData.TemplateDataAttr();
            keyword3.setDataValue(BigDecimalUtil.to2Point(payTbillSold.getGoldPrice()).toString());
            wxParamMap.put("keyword3", keyword3);

            WxNotifyData.TemplateDataAttr keyword4 = new WxNotifyData.TemplateDataAttr();
            keyword4.setDataValue(BigDecimalUtil.to2Point(fee).toString());
            wxParamMap.put("keyword4", keyword4);

            WxNotifyData.TemplateDataAttr keyword5 = new WxNotifyData.TemplateDataAttr();
            keyword5.setDataValue(DateUtils.dateToStr(new Date(), DateUtils.patter));
            wxParamMap.put("keyword5", keyword5);

            WxNotifyData.TemplateDataAttr remark = new WxNotifyData.TemplateDataAttr();
            remark.setDataValue(wxTemplateEnum.getRemark());
            wxParamMap.put("remark", remark);

            wxNotifyData.setData(wxParamMap);
            wxMessageParamBean.setTemplateData(wxNotifyData);
            amqpTemplate.convertAndSend(QUEUE_MSG_WX_SEND, wxMessageParamBean);
            cacheUtilsService.deleteCache(hashKey);
            return saleNO;
        } finally {
            redisGlobalLock.unlock(key);
        }
    }


    @Override
    public String saleJob(String orderNO, BigDecimal goldPrice) {
        log.info("安稳金到期自动出售执行方法,请求参数：提单编号=" + orderNO + " 出售金价：=" + goldPrice);
        PayTbill payTbill = payTbillMapper.selectByOrderNO(orderNO);
        if (payTbill == null || payTbill.getStatus() != TbillStatusEnum.PAY_SUCCESS.getStatus()) {
            return null;
        }
        PayTbillStatistics payTbillStatistics = payTbillStatisticsMapper.selectByMemberId(payTbill.getMemberId());
        if (payTbillStatistics == null) {
            return null;
        }
        BigDecimal weight = new BigDecimal(payTbill.getTotalGram());
        String date = UF.getFormatDateNow();
        SerializeObject result = rateSettingsService.get(RateKeyEnum.BUY_SELL_GRAM.getKey());
        if (result.getData() != null) {
            Map<String, Object> map = (Map<String, Object>) result.getData();
            String maxGramPerday = String.valueOf(map.get("sellMaxGramPerDay"));
            if (!"0".equals(maxGramPerday)) {
                BigDecimal sellTotalGram = new BigDecimal(payTbillSoldMapper.sumSomedaySoldGram(payTbill.getMemberId(), date));
                sellTotalGram = BigDecimalUtil.subtract(new BigDecimal(maxGramPerday), sellTotalGram);
                if (weight.compareTo(sellTotalGram) > 0) {
                    Ensure.that(true).isTrue("17000710");
                }
            }
        }
        String saleNO = OrderNOPrefixEnum.TS.name() + SerialNumberWorker.getInstance().nextId();
        // 1. 添加出售记录；
        PayTbillSold payTbillSold = new PayTbillSold();
        payTbillSold.setTbillNO(orderNO);
        payTbillSold.setOrderNO(saleNO);
        payTbillSold.setGoldPrice(goldPrice);
        payTbillSold.setTotalAmount(BigDecimalUtil.to2Point(new BigDecimal(payTbill.getTotalGram()).multiply(goldPrice)));
        BigDecimal fee = getFee(payTbill.getMemberId(), new BigDecimal(payTbill.getTotalGram()), goldPrice);
        payTbillSold.setFee(fee);
        BigDecimal couponAmount = BigDecimal.ZERO;
        if (StringUtils.isNotBlank(payTbill.getCouponId())) {
            if (payTbill.getLeasebackTimes() == 0) {
                LocalDateTime startTime = UF.getDateTime(payTbill.getAddTime());
                LocalDateTime endTime = LocalDateTime.now();
                Duration duration = Duration.between(startTime, endTime);
                long days = duration.toDays();
                //long hours = duration.toHours();
                if (days < 30) {
                    couponAmount = payTbill.getCouponGram().multiply(payTbill.getGoldPrice());
                }
            }
        }
        payTbillSold.setCouponAmount(couponAmount);
        payTbillSold.setActualAmount(BigDecimalUtil.to2Point(new BigDecimal(payTbill.getTotalGram()).multiply(goldPrice).subtract(fee).subtract(payTbillSold.getCouponAmount())));
        payTbillSold.setAddTime(UF.getFormatDateTime(UF.getDateTime()));
        payTbillSold.setSuccessTime(UF.getFormatDateTime(UF.getDateTime()));
        int rows = payTbillSoldMapper.insert(payTbillSold);
        Ensure.that(rows).isLt(1, "00000005");
        // 2. 更改提单表信息；
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("orderNO", orderNO);
        param.put("status", TbillStatusEnum.SOLD.getStatus());
        param.put("modifyTime", UF.getFormatDateTime(UF.getDateTime()));
        param.put("readed", 0);
        rows = payTbillMapper.update(param);
        Ensure.that(rows).isLt(1, "00000005");
        // 3. 更改提单统计表信息；
        Map<String, Object> staParam = new HashMap<String, Object>();
        staParam.put("memberId", payTbill.getMemberId());
        staParam.put("pendingBills", payTbillStatistics.getPendingBills() - 1);
        staParam.put("pendingGram", payTbillStatistics.getPendingGram() - payTbill.getTotalGram());
        staParam.put("soldBills", payTbillStatistics.getSoldBills() + 1);
        staParam.put("soldGram", payTbillStatistics.getSoldGram() + payTbill.getTotalGram());
        staParam.put("soldAmount", payTbillStatistics.getSoldAmount().add(payTbillSold.getActualAmount()));
        rows = payTbillStatisticsMapper.update(staParam);
        Ensure.that(rows).isLt(1, "00000005");
        // 4. 奖励发放
        MemberAccount memberAccount = memberAccountMapper.findByMemberId(payTbill.getMemberId());
        Ensure.that(memberAccount == null).isTrue("17000421");
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id", memberAccount.getId());
        map.put("fundAmount", memberAccount.getFundAmount().add(payTbillSold.getActualAmount()));
        map.put("usableAmount", memberAccount.getUsableAmount().add(payTbillSold.getActualAmount()));
        rows = memberAccountMapper.updateByPrimaryKeySelective(map);
        Ensure.that(rows).isLt(1, "00000005");
        // 5. 新增收支记录
        Bill billBean = new Bill();
        billBean.setOrderId(SerialNumberWorker.getInstance().nextId());
        billBean.setMemberId(payTbill.getMemberId());
        billBean.setAmount(payTbillSold.getTotalAmount());
        billBean.setFee(payTbillSold.getFee());
        billBean.setActualAmount(payTbillSold.getActualAmount());
        billBean.setType(BillType.INCOME.getValue());
        billBean.setId(UF.getRandomUUID());
        billBean.setTradeType(TradeType.TBILL_SOLD.getValue());
        billBean.setOrderId(SerialNumberWorker.getInstance().nextId());
        rows = billMapper.insert(billBean);
        Ensure.that(rows).isLt(1, "00000005");
        // 6. 提单出售手续费收支记录
        if (fee.doubleValue() > 0) {
            billBean = new Bill();
            billBean.setOrderId(SerialNumberWorker.getInstance().nextId());
            billBean.setMemberId(payTbill.getMemberId());
            billBean.setAmount(fee);
            billBean.setFee(BigDecimal.ZERO);
            billBean.setActualAmount(fee.subtract(BigDecimal.ZERO));
            billBean.setType(BillType.OUTLAY.getValue());
            billBean.setId(UF.getRandomUUID());
            billBean.setTradeType(TradeType.TBILL_SOLD_FEE.getValue());
            billBean.setOrderId(SerialNumberWorker.getInstance().nextId());
            rows = billMapper.insert(billBean);
            Ensure.that(rows).isLt(1, "00000005");
        }
        PayTbillStatus payTbillStatus = new PayTbillStatus();
        payTbillStatus.setTbillNO(orderNO);
        payTbillStatus.setOrderNO(SerialNumberWorker.getInstance().nextId());
        payTbillStatus.setAddTime(UF.getFormatDateTime(UF.getDateTime()));
        payTbillStatus.setType(TbillTypeEnum.SOLD.getValue());
        payTbillStatus.setStatus(TbillStatusEnum.SOLD.getStatus());
        payTbillStatus.setRemark(TbillStatusRemark.SOLD.getValue());
        payTbillStatus.setModifyTime(UF.getFormatDateTime(UF.getDateTime()));
        payTbillStatusMapper.insert(payTbillStatus);
        // 7. 消息通知
        Msg msg = new Msg();
        msg.setMemberId(payTbill.getMemberId());
        msg.setType(CommonConstants.MsgType.SELL_GOLD.getIndex());
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("reduceGram", String.valueOf(payTbill.getTotalGram()));
        paramMap.put("gram", String.valueOf(payTbillStatistics.getPendingGram() - payTbill.getTotalGram()));
        msg.setParamMap(paramMap);
        amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);

        WxMessageParamBean wxMessageParamBean = new WxMessageParamBean();
        wxMessageParamBean.setMemberId(payTbill.getMemberId());
        wxMessageParamBean.setType(WxTemplateEnum.SALE_GOLD_SUCCEED.getType());
        WxTemplateEnum wxTemplateEnum = WxTemplateEnum.getWxTemplateByCode(WxTemplateEnum.SALE_GOLD_SUCCEED.getType());
        WxNotifyData wxNotifyData = new WxNotifyData();

        Map<String, WxNotifyData.TemplateDataAttr> wxParamMap = new HashMap();
        WxNotifyData.TemplateDataAttr first = new WxNotifyData.TemplateDataAttr();
        first.setDataValue(wxTemplateEnum.getFirstData().replace("{weight}", String.valueOf(payTbill.getTotalGram())).
                replace("{balance}", String.valueOf(payTbillStatistics.getPendingGram() - payTbill.getTotalGram())).
                replace("{money}", String.valueOf(payTbillSold.getActualAmount())));
        wxParamMap.put("first", first);

        WxNotifyData.TemplateDataAttr keyword1 = new WxNotifyData.TemplateDataAttr();
        keyword1.setDataValue(String.valueOf(payTbillSold.getActualAmount()));
        wxParamMap.put("keyword1", keyword1);

        WxNotifyData.TemplateDataAttr keyword2 = new WxNotifyData.TemplateDataAttr();
        keyword2.setDataValue(String.valueOf(payTbill.getTotalGram()));
        wxParamMap.put("keyword2", keyword2);

        WxNotifyData.TemplateDataAttr keyword3 = new WxNotifyData.TemplateDataAttr();
        keyword3.setDataValue(BigDecimalUtil.to2Point(payTbillSold.getGoldPrice()).toString());
        wxParamMap.put("keyword3", keyword3);

        WxNotifyData.TemplateDataAttr keyword4 = new WxNotifyData.TemplateDataAttr();
        keyword4.setDataValue(BigDecimalUtil.to2Point(fee).toString());
        wxParamMap.put("keyword4", keyword4);

        WxNotifyData.TemplateDataAttr keyword5 = new WxNotifyData.TemplateDataAttr();
        keyword5.setDataValue(DateUtils.dateToStr(new Date(), DateUtils.patter));
        wxParamMap.put("keyword5", keyword5);

        WxNotifyData.TemplateDataAttr remark = new WxNotifyData.TemplateDataAttr();
        remark.setDataValue(wxTemplateEnum.getRemark());
        wxParamMap.put("remark", remark);

        wxNotifyData.setData(wxParamMap);
        wxMessageParamBean.setTemplateData(wxNotifyData);
        amqpTemplate.convertAndSend(QUEUE_MSG_WX_SEND, wxMessageParamBean);
        return saleNO;
    }

    @Override
    public List<PayTbillSold> query(String mobile, String name, int startGram, int endGram, String startDate, String endDate, String order, String sort, int offset, int size, Integer[] productType,
                                    String tbillNO, String totalAmountMin, String totalAmountMax, String actualAmountMin, String actualAmountMax) {
        List<String> orders = Arrays.asList("total_gram", "add_time", "success_time", "total_amount");
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(mobile)) {
            params.put("mobile", mobile);
        }
        if (StringUtils.isNotBlank(name)) {
            params.put("name", name);
        }
        if (startGram >= 0) {
            params.put("startGram", startGram);
        }
        if (endGram >= 0) {
            params.put("endGram", endGram);
        }
        if (StringUtils.isNotBlank(startDate)) {
            params.put("startDate", startDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            params.put("endDate", endDate);
        }
        if (orders.contains(order)) {
            params.put("order", order);
            params.put("sort", "desc");
            if (StringUtils.equalsIgnoreCase(sort, "asc") || StringUtils.equalsIgnoreCase(sort, "desc")) {
                params.put("sort", sort);
            }
        }
        if (productType != null && productType.length > 0) {
            params.put("productType", productType);
        }

        if (StringUtils.isNotBlank(tbillNO)) {
            params.put("tbillNO", tbillNO);
        }

        if (StringUtils.isNotBlank(totalAmountMin)) {
            params.put("totalAmountMin", totalAmountMin);
        }

        if (StringUtils.isNotBlank(totalAmountMax)) {
            params.put("totalAmountMax", totalAmountMax);
        }

        if (StringUtils.isNotBlank(actualAmountMin)) {
            params.put("actualAmountMin", actualAmountMin);
        }

        if (StringUtils.isNotBlank(actualAmountMax)) {
            params.put("actualAmountMax", actualAmountMax);
        }

        params.put("offset", offset);
        params.put("size", size);
        return payTbillSoldMapper.query(params);
    }

    @Override
    public int count(String mobile, String name, int startGram, int endGram, String startDate, String endDate, Integer[] productType,
                     String tbillNO, String totalAmountMin, String totalAmountMax, String actualAmountMin, String actualAmountMax) {
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(mobile)) {
            params.put("mobile", mobile);
        }
        if (StringUtils.isNotBlank(name)) {
            params.put("name", name);
        }
        if (startGram >= 0) {
            params.put("startGram", startGram);
        }
        if (endGram >= 0) {
            params.put("endGram", endGram);
        }
        if (StringUtils.isNotBlank(startDate)) {
            params.put("startDate", startDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            params.put("endDate", endDate);
        }

        if (productType != null && productType.length > 0) {
            params.put("productType", productType);
        }

        if (StringUtils.isNotBlank(tbillNO)) {
            params.put("tbillNO", tbillNO);
        }

        if (StringUtils.isNotBlank(totalAmountMin)) {
            params.put("totalAmountMin", totalAmountMin);
        }

        if (StringUtils.isNotBlank(totalAmountMax)) {
            params.put("totalAmountMax", totalAmountMax);
        }

        if (StringUtils.isNotBlank(actualAmountMin)) {
            params.put("actualAmountMin", actualAmountMin);
        }

        if (StringUtils.isNotBlank(actualAmountMax)) {
            params.put("actualAmountMax", actualAmountMax);
        }

        return payTbillSoldMapper.count(params);
    }

    @Override
    public List<PayTbillSold> queryIncome(String mobile, String name, int startGram, int endGram, String startDate, String endDate, String order, String sort,Integer[] productType,
                                    String tbillNo, String buyTotalAmountMin, String buyTotalAmountMax, String soldTotalAmountMin, String soldTotalAmountMax) {
        List<String> orders = Arrays.asList("total_gram", "buyTotalAmount", "total_amount", "incomeAmount", "add_time");
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(mobile)) {
            params.put("mobile", mobile);
        }
        if (StringUtils.isNotBlank(name)) {
            params.put("name", name);
        }
        if (startGram >= 0) {
            params.put("startGram", startGram);
        }
        if (endGram >= 0) {
            params.put("endGram", endGram);
        }
        if (StringUtils.isNotBlank(startDate)) {
            params.put("startDate", startDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            params.put("endDate", endDate);
        }
        if (orders.contains(order)) {
            params.put("order", order);
            params.put("sort", "desc");
            if (StringUtils.equalsIgnoreCase(sort, "asc") || StringUtils.equalsIgnoreCase(sort, "desc")) {
                params.put("sort", sort);
            }
        }
        if (productType != null && productType.length > 0) {
            params.put("productType", productType);
        }

        if (StringUtils.isNotBlank(tbillNo)) {
            params.put("tbillNo", tbillNo);
        }

        if (StringUtils.isNotBlank(buyTotalAmountMin)) {
            params.put("buyTotalAmountMin", buyTotalAmountMin);
        }

        if (StringUtils.isNotBlank(buyTotalAmountMax)) {
            params.put("buyTotalAmountMax", buyTotalAmountMax);
        }

        if (StringUtils.isNotBlank(soldTotalAmountMin)) {
            params.put("soldTotalAmountMin", soldTotalAmountMin);
        }

        if (StringUtils.isNotBlank(soldTotalAmountMax)) {
            params.put("soldTotalAmountMax", soldTotalAmountMax);
        }

        return payTbillSoldMapper.queryIncome(params);
    }

}
